package io.framework.modules.water.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.framework.common.annotation.LogOperation;
import io.framework.common.exception.ErrorCode;
import io.framework.common.utils.ConvertUtils;
import io.framework.common.utils.DateUtils;
import io.framework.common.utils.Result;
import io.framework.common.validator.AssertUtils;
import io.framework.modules.station.dto.StationDTO;
import io.framework.modules.station.service.StationService;
import io.framework.modules.water.dto.*;
import io.framework.modules.water.entity.*;
import io.framework.modules.water.service.*;
import io.framework.modules.water.utils.WaterFileCommonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * /**
 * 〈水数据上传〉
 *
 * @Author GJQ
 * @Create 2020/5/20
 * @Since 1.0.0
 */
@RestController
@Api(tags = "水环境监测数据上传")
public class UploadWaterDataController {

    Logger logger = LoggerFactory.getLogger(UploadWaterDataController.class);

    @Value("${file.upload.path}")
    private String FILE_UPLOAD_PATH;

    /**
     * 重点治理城镇内河（湖）水质状况
     */
    @Autowired
    private WaterCityRiverService waterCityRiverService;

    /**
     * 饮用水源地/检测断面 水质类别表
     */
    @Autowired
    private WaterService waterService;

    /**
     * 地表水 监测断面水质评价表
     */
    @Autowired
    private WaterFractureSurfaceService waterFractureSurfaceService;

    /**
     * 城镇内河(湖)水环境主要监测结果
     */
    @Autowired
    private WaterMonitorService waterMonitorService;

    /**
     * 站点
     */
    @Autowired
    private StationService stationService;

    /**
     * 海洋浮标点信息
     */
    @Autowired
    private OceanBuoyPointService oceanBuoyPointService;

    /**
     * 滨海旅游区海水
     */
    @Autowired
    private WaterBinhaiService waterBinhaiService;

    /**
     * 近岸海域海水
     */
    @Autowired
    private WaterNearshoreService waterNearshoreService;

    @GetMapping("water/upload/checkData")
    @ApiOperation("验证水环境数据上传")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "1-重点治理城镇内河（湖）水质状况 2-地表水常规监测水质类别表 3-城镇内河（湖）水环境月报 4-城市集中式饮用水源地水质类别表", paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "month", value = "时间月份 例：2020-03", paramType = "query", dataType = "Integer", required = true),
    })
    public Result checkData(@ApiIgnore @RequestParam Map<String, Object> params) {
        logger.info("=======================验证水环境数据上传=======================");
        Integer type = Integer.parseInt(params.get("type").toString());
        String month = params.get("month").toString();
        String stationCode = params.get("stationCode").toString();
        Boolean flag = true;
        //1-重点治理城镇内河（湖）水质状况
        //2-地表水常规监测水质类别表
        //3-城镇内河（湖）水环境月报
        //4-城市集中式饮用水源地水质类别表
        //5-海洋浮标点信息
        //6-滨海
        //7-近岸海域
        if (type == 4 || type == 2) {
            flag = waterService.checkData(type, month);
        } else if (type == 3) {
            flag = waterMonitorService.checkData(month);
        } else if (type == 5) {
            flag = oceanBuoyPointService.checkData(stationCode, month);
        } else if (type == 6) {
            flag = waterBinhaiService.checkData(month);
        } else if (type == 7) {
            flag = waterNearshoreService.checkData(month);
        } else if (type == 1) {
            flag = waterCityRiverService.checkData(month);
        }
        if (flag) {
            return new Result().error(ErrorCode.UPLOAD_FILE_CHECK);
        }
        return new Result();
    }

    @PostMapping("water/upload/datas/uploadFile")
    @ApiOperation("水环境上传数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "1-重点治理城镇内河（湖）水质状况 2-地表水常规监测水质类别表 " +
                    "3-城镇内河（湖）水环境月报 4-城市集中式饮用水源地水质类别表" +
                    "5-海洋浮标点位监测数据  6-滨海旅游区海水" +
                    "7-近岸海域海水", paramType = "query", dataType = "int", required = true),
            @ApiImplicitParam(name = "month", value = "时间月份 例：2020-03", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "multipartFile", value = "文件", paramType = "query", dataType = "file", required = true),
    })
    @LogOperation("上传水环境站点监测数据")
    @RequiresPermissions("water:info:upload")
    @SuppressWarnings("all")
    public Result readWaterInfo(Integer type, String month, String stationCode, MultipartFile multipartFile) {
        String filename = multipartFile.getOriginalFilename();
        if (StringUtils.isEmpty(filename)) {
            return new Result().error(ErrorCode.UPLOAD_FILE_EMPTY);
        }
        File file = new File(FILE_UPLOAD_PATH + DateUtil.format(new Date(), "yyyy-MM-dd"));
        if (!file.exists()) {
            file.mkdirs();
        }
        File excelFile = new File(file, File.separator + DateUtil.format(new Date(), "HHmmss") + filename.substring(filename.indexOf(".")));
        try {
            multipartFile.transferTo(excelFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String filePath = excelFile.getPath();
        if (type == 1) {
            logger.info("=======================1-重点治理城镇内河（湖）水质状况=======================");

            List<WaterCityRiverDTO> list = new ArrayList<>();
            //获取第一个表格数据
            list.addAll(WaterFileCommonUtil.getWaterDTOInfo3(filePath, month, 1));
            //获取第二个表格数据
            list.addAll(WaterFileCommonUtil.getWaterDTOInfo3(filePath, month, 2));
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(v -> {
                    Map<String, Object> map = new HashMap<>(2);
                    map.put("name", v.getStationName());
                    map.put("type", 2);
                    //水： 1-地表水 2-城镇内河 3-重点治理城镇内河 4-引用水源地 5-海洋浮标点
                    map.put("control", 3);
                    List<StationDTO> stationDTOS = stationService.getStationInfoByParams(map);
                    if (CollectionUtils.isNotEmpty(stationDTOS)) {
                        v.setStationId(stationDTOS.get(0).getId());
                    }
                });
                month = DateUtils.format(DateUtils.parse(month, DateUtils.DATE_MONTH_PATTERN), DateUtils.DATE_MONTH_PATTERN);
                waterCityRiverService.deleteInfoByDate(month);
                waterCityRiverService.insertBatch(ConvertUtils.sourceToTarget(list, WaterCityRiverEntity.class));
            }
        } else if (type == 2) {
            logger.info("=======================2-地表水常规监测水质类别表=======================");

            List<WaterDTO> waterDTOList = WaterFileCommonUtil.getWaterDTOInfo1(filePath, 2, month, 1);
            String year = DateUtils.format(DateUtils.parse(month, DateUtils.DATE_MONTH_PATTERN), DateUtils.DATE_YEAR_PATTERN);
            if (CollectionUtils.isNotEmpty(waterDTOList)) {
                waterDTOList.forEach(v -> {
                    Map<String, Object> map = new HashMap<>(2);
                    map.put("type", 2);
                    map.put("name", v.getName());
                    //水： 1-地表水 2-城镇内河 3-重点治理城镇内河 4-引用水源地 5-海洋浮标点
                    map.put("control", 1);
                    List<StationDTO> stationDTOS = stationService.getStationInfoByParams(map);
                    if (CollectionUtils.isNotEmpty(stationDTOS)) {
                        v.setStationId(stationDTOS.get(0).getId());
                    }
                });
                waterService.deleteInfoByDate(2, year);
                waterService.insertBatch(ConvertUtils.sourceToTarget(waterDTOList, WaterEntity.class));
            }
            List<WaterFractureSurfaceDTO> waterFractureSurfaceDTOList = WaterFileCommonUtil.getWaterDTOInfo2(filePath, type, month, 2);
            if (CollectionUtils.isNotEmpty(waterFractureSurfaceDTOList)) {
                waterFractureSurfaceDTOList.forEach(v -> {
                    Map<String, Object> map = new HashMap<>(2);
                    map.put("name", v.getName());
                    map.put("type", 2);
                    //水： 1-地表水 2-城镇内河 3-重点治理城镇内河 4-引用水源地 5-海洋浮标点
                    map.put("control", 1);
                    List<StationDTO> stationDTOS = stationService.getStationInfoByParams(map);
                    if (CollectionUtils.isNotEmpty(stationDTOS)) {
                        v.setStationId(stationDTOS.get(0).getId());
                    }
                });
                waterFractureSurfaceService.deleteInfoByDate(year);
                waterFractureSurfaceService.insertBatch(ConvertUtils.sourceToTarget(waterFractureSurfaceDTOList, WaterFractureSurfaceEntity.class));
            }
        } else if (type == 3) {
            logger.info("=======================3-城镇内河（湖）水环境月报=======================");

            List<WaterMonitorDTO> list = new ArrayList<>();
            //set=1 第一个表格数据 海水河流型
            list.addAll(WaterFileCommonUtil.getWaterDTOInfo4(filePath, month, 1));
            //set=2 第一个表格数据 湖库型
            list.addAll(WaterFileCommonUtil.getWaterDTOInfo4(filePath, month, 2));
            //set=3 第一个表格数据 淡水河流型
            list.addAll(WaterFileCommonUtil.getWaterDTOInfo4(filePath, month, 3));
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(v -> {
                    Map<String, Object> map = new HashMap<>(2);
                    map.put("type", 2);
                    map.put("name", v.getStationName());
                    //水： 1-地表水 2-城镇内河 3-重点治理城镇内河 4-引用水源地 5-海洋浮标点
                    map.put("control", 2);
                    List<StationDTO> stationDTOS = stationService.getStationInfoByParams(map);
                    if (CollectionUtils.isNotEmpty(stationDTOS)) {
                        v.setStationId(stationDTOS.get(0).getId());
                    }
                });
                month = DateUtils.format(DateUtils.parse(month, DateUtils.DATE_MONTH_PATTERN), DateUtils.DATE_MONTH_PATTERN);
                waterMonitorService.deleteInfoByMonth(month);
                waterMonitorService.insertBatch(ConvertUtils.sourceToTarget(list, WaterMonitorEntity.class));
            }
        } else if (type == 4) {
            logger.info("=======================4-城市集中式饮用水源地水质类别表=======================");

            List<WaterDTO> waterDTOList = WaterFileCommonUtil.getWaterDTOInfo1(filePath, 1, month, 1);
            if (CollectionUtils.isNotEmpty(waterDTOList)) {
                waterDTOList.forEach(v -> {
                    Map<String, Object> map = new HashMap<>(2);
                    map.put("name", v.getName());
                    map.put("type", 2);
                    //水： 1-地表水 2-城镇内河 3-重点治理城镇内河 4-引用水源地 5-海洋浮标点
                    map.put("control", 4);
                    List<StationDTO> stationDTOS = stationService.getStationInfoByParams(map);
                    if (CollectionUtils.isNotEmpty(stationDTOS)) {
                        v.setStationId(stationDTOS.get(0).getId());
                    }
                });
                String year = DateUtils.format(DateUtils.parse(month, DateUtils.DATE_MONTH_PATTERN), DateUtils.DATE_YEAR_PATTERN);
                waterService.deleteInfoByDate(1, year);
                waterService.insertBatch(ConvertUtils.sourceToTarget(waterDTOList, WaterEntity.class));
            }
        } else if (type == 5) {
            logger.info("=======================海洋浮标点位监测数据=======================");

            AssertUtils.isBlank("stationCode", ErrorCode.NOT_NULL);
            List<OceanBuoyPointDTO> list = WaterFileCommonUtil.getOceanPointInfo(stationCode, filePath);
            if (CollectionUtils.isNotEmpty(list)) {
                //取出时间
                List<Date> dateSet = list.stream().map(OceanBuoyPointDTO::getDate).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());
                //删除历史
                oceanBuoyPointService.deleteBatchByDate(stationCode, dateSet);
                //添加新数据
                oceanBuoyPointService.insertBatch(ConvertUtils.sourceToTarget(list, OceanBuoyPointEntity.class));
            }
        } else if (type == 6) {
            logger.info("=======================滨海旅游区海水=======================");

            List<WaterBinhaiDTO> list = WaterFileCommonUtil.getWaterBinhaiData(filePath, month, 1);
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(v -> {
                    Map<String, Object> map = new HashMap<>(2);
                    map.put("type", 2);
                    map.put("name", v.getName());
                    //水： 1-地表水 2-城镇内河 3-重点治理城镇内河 4-引用水源地 5-海洋浮标点
                    map.put("control", 7);
                    List<StationDTO> stationDTOS = stationService.getStationInfoByParams(map);
                    if (CollectionUtils.isNotEmpty(stationDTOS)) {
                        v.setStationId(stationDTOS.get(0).getId());
                    }
                });
                //删除历史数据
                waterBinhaiService.deleteInfoByDate(month);
                //添加新数据
                waterBinhaiService.insertBatch(ConvertUtils.sourceToTarget(list, WaterBinhaiEntity.class));
            }
        } else if (type == 7) {
            logger.info("=======================近岸海域海水=======================");

            List<WaterNearshoreDTO> list = WaterFileCommonUtil.getWaterNearShoreData(filePath, month, 1);
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(v -> {
                    Map<String, Object> map = new HashMap<>(2);
                    map.put("type", 2);
                    map.put("name", v.getName());
                    //水： 1-地表水 2-城镇内河 3-重点治理城镇内河 4-引用水源地 5-海洋浮标点
                    map.put("control", 6);
                    List<StationDTO> stationDTOS = stationService.getStationInfoByParams(map);
                    if (CollectionUtils.isNotEmpty(stationDTOS)) {
                        v.setStationId(stationDTOS.get(0).getId());
                    }
                });
                //删除历史数据
                waterNearshoreService.deleteInfoByDate(month);
                //添加新数据
                waterNearshoreService.insertBatch(ConvertUtils.sourceToTarget(list, WaterNearshoreEntity.class));
            }
        } else {
            return new Result().error(ErrorCode.UPLOAD_FILE_TYPE_NOTNULL);
        }
        return new Result().ok("上传成功");
    }

}
